package cn.pink.common.id;


import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 唯一编号生成器
 *
 * TODO 时钟回拨存在生成id重复的风险
 *
 * @author Pink
 */
public final class UniqueID {
  private static final Seed DEFAULT_ID_ADDER = Seed.create();
  private static AtomicLong atomicLong = new AtomicLong();

  private UniqueID() {}

  /**
   * 获取下一个自增长ID（用于不持久化的唯一ID）
   */
  public static long autoIncrement() {
    return atomicLong.incrementAndGet();
  }

  /**
   * 生成唯一ID
   */
  public static long nextID(int areaID, Seed seed) {
    // areaID24+时间29+自增11
    return (((long) (areaID & 0x00FFFFFF)) << 40) | seed.next();
  }

  public static long nextID(AreaID areaID, Seed seed) {
    return nextID(areaID.areaID(), seed);
  }

  public static long nextID(AreaID areaID) {
    return nextID(areaID, DEFAULT_ID_ADDER);
  }

  public static long nextID(int areaID) {
    return nextID(areaID, DEFAULT_ID_ADDER);
  }

  public static long nextID() {
    return nextID(1);
  }

  /**
   * 生成全球唯一Id
   */
  public static String UUID() {
    return UUID.randomUUID().toString().replace("-", "").toUpperCase();
  }

  /** 种子 */
  public static class Seed {
    private final transient AtomicLong origin =
        new AtomicLong(((System.currentTimeMillis() / 1000) & 0x000000001FFFFFFFL) << 11);

    public static Seed create() {
      return new Seed();
    }

    private Seed() {}

    private long next() {
      return origin.getAndIncrement();
    }
  }
}
